home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / LANG / C / LIB / UNIXLIB37B / !UnixLib37 / src / c / system < prev    next >
Text File  |  1996-11-09  |  4KB  |  141 lines

  1. /****************************************************************************
  2.  *
  3.  * $Source: /unixb/home/unixlib/source/unixlib37/src/c/RCS/system,v $
  4.  * $Date: 1996/10/30 21:58:59 $
  5.  * $Revision: 1.4 $
  6.  * $State: Rel $
  7.  * $Author: unixlib $
  8.  *
  9.  * $Log: system,v $
  10.  * Revision 1.4  1996/10/30 21:58:59  unixlib
  11.  * Massive changes made by Nick Burret and Peter Burwood.
  12.  *
  13.  * Revision 1.3  1996/09/16 21:23:52  unixlib
  14.  * CL_0002 Nick Burret
  15.  * Minor changes to file handling
  16.  * Change most error numbers, and use in assembler sources (SJC)
  17.  * Various minor bug fixes and compatability changes.
  18.  *
  19.  * Revision 1.2  1996/05/06 09:03:13  unixlib
  20.  * Updates to sources made by Nick Burrett, Peter Burwood and Simon Callan.
  21.  * Saved for 3.7a release.
  22.  *
  23.  * Revision 1.1  1996/04/19 21:26:42  simon
  24.  * Initial revision
  25.  *
  26.  ***************************************************************************/
  27.  
  28. static const char rcs_id[] = "$Id: system,v 1.4 1996/10/30 21:58:59 unixlib Rel $";
  29.  
  30. /* c.system: Written by Nick Burrett, 6 October 1996.  */
  31.  
  32. #include <stddef.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <unistd.h>
  36. #include <sys/wait.h>
  37. #include <signal.h>
  38. #include <sys/types.h>
  39.  
  40.  
  41. /* Execute LINE as a shell command, returning its status.  */
  42. int system (const char *line)
  43. {
  44.   int status, save;
  45.   pid_t pid;
  46.   struct sigaction sa, intr, quit;
  47.   sigset_t block, omask;
  48.  
  49.   if (line == NULL)
  50.     return 1;
  51.  
  52.   sa.sa_handler = SIG_IGN;
  53.   sa.sa_flags = 0;
  54.   sigemptyset (&sa.sa_mask);
  55.  
  56.   /* Ignore signals SIGINT and SIGQUIT.  */
  57.  
  58.   if (sigaction (SIGINT, &sa, &intr))
  59.     return -1;
  60.  
  61.   if (sigaction (SIGQUIT, &sa, &quit))
  62.     {
  63.       /* Bit of an error, restore SIGINT and preserve the errno.  */
  64.       save = errno;
  65.       (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL);
  66.       errno = save;
  67.       return -1;
  68.     }
  69.  
  70.   /* Block SIGCHLD.  */
  71.   sigemptyset (&block);
  72.   sigaddset (&block, SIGCHLD);
  73.   save = errno;
  74.   if (sigprocmask (SIG_BLOCK, &block, &omask))
  75.     {
  76.       if (errno == ENOSYS)
  77.     errno = save;
  78.       else
  79.     {
  80.       /* Awkward error, so restore signal handlers and return.  */
  81.       save = errno;
  82.       (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL);
  83.       (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
  84.       errno = save;
  85.       return -1;
  86.     }
  87.     }
  88.  
  89.   /* vfork the process.  */
  90.   pid = vfork ();
  91.   if (pid == (pid_t) 0)
  92.     {
  93.       char *shell, *path;
  94.  
  95.       /* Restore the signals.  */
  96.       sigaction (SIGINT, &intr, (struct sigaction *) NULL);
  97.       sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
  98.       /* Could deliver a few pending signals here.  */
  99.       sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL);
  100.  
  101.       /* Execute the shell.  */
  102.       if (!(path = getenv ("SHELL")))
  103.     {
  104.       if (*line == '*')
  105.         execl ((char *) line, 0);
  106.       else
  107.         execl ("*", "", (char *) line, 0);
  108.       _exit (1);
  109.     }
  110.  
  111.       shell = strrchr (path, '/');
  112.       if (shell)
  113.     shell++;
  114.       else
  115.     shell = path;
  116.       execl (path, shell, "-c", (char *)line, 0);
  117.       _exit (1);
  118.     }
  119.   else if (pid < (pid_t) 0)
  120.     /* The fork failed.  */
  121.     status = -1;
  122.   else
  123.     if (waitpid (pid, &status, 0) != pid)
  124.       status = -1;
  125.  
  126.   /* Got here on a vfork failure. So restore signals and the blocking
  127.      mask then exit. */
  128.   save = errno;
  129.   if ((sigaction (SIGINT, &intr, (struct sigaction *) NULL) |
  130.        sigaction (SIGQUIT, &quit, (struct sigaction *) NULL) |
  131.        sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL)) != 0)
  132.     {
  133.       if (errno == ENOSYS)
  134.     errno = save;
  135.       else
  136.     return -1;
  137.     }
  138.  
  139.   return status;
  140. }
  141.